package five;

import java.awt.Color;

import java.awt.Font;

import java.awt.Graphics;

import java.awt.Toolkit;

import java.awt.event.MouseEvent;

import java.awt.event.MouseListener;

import java.awt.image.BufferedImage;

import javax.swing.JFrame;

import javax.swing.JOptionPane;

public class FiveChessFrame extends JFrame implements Runnable,MouseListener{

    /**

     *

     */

    private static final long serialVersionUID = 1L;

//游戏界面大小

    int width=Toolkit.getDefaultToolkit().getScreenSize().width;

    int height=Toolkit.getDefaultToolkit().getScreenSize().height;

    int x,y; //鼠标坐标

    int[][]allChess=new int[15][15]; //保存棋盘,0表示无子,1表示黑子,2表示白字

    Boolean isblack=true; //当前下子是黑子还是白字，true代表黑子，false代表白子

    Boolean canPlay=true; //标始当前游戏是否结束

    String message="黑方先行";

    String blackMessage="无限制";

    String whiteMessage="无限制";

//保存棋谱,记录双方每一步落子的位置

    int[]chessX=new int[255];

    int[]chessY=new int[255];

    int countX,countY;

//默认设置无时间限制

    int maxTime=0; //保存最大时间

    int blackTime=0;

    int whiteTime=0; //保存黑白方所剩余的时间

    Thread timer=new Thread(this);

    public FiveChessFrame(){

        this.setTitle("五子棋游戏");

        this.setSize(500, 500);

        this.setLocation((width - 500) / 2, (height - 500) / 2);

        this.setResizable(false);

        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        this.setVisible(true);

        this.repaint();

        this.addMouseListener(this);

        timer.start(); //开启计时线程

        timer.suspend();

    }

//画棋盘界面

    public void paint(Graphics g){

//双缓冲技术

        BufferedImage buf=new BufferedImage(500,500,BufferedImage.TYPE_INT_RGB);

        Graphics g1=buf.createGraphics(); //创建画笔

        g1.setColor(new Color(0,169,158)); //设置画笔颜色

        g1.fill3DRect(43,60,375,375,true);

        for(int i=0;i<=15;i++){

            g1.setColor(Color.WHITE);

            g1.drawLine(43,60+i*25,375+43,60+i*25);//画棋盘横线

            g1.drawLine(43+i*25,60,43+i*25,375+60); //画棋盘竖线

        }

        g1.setFont(new Font("黑体",Font.BOLD,20));

        g1.drawString("游戏信息: "+message,50,50);

        g1.drawRect(30,440,180,40);

        g1.drawRect(250,440,180,40); //画黑方时间与白方时间字符串的边框

        g1.setFont(new Font("宋体",0,12));

        g1.drawString("黑方时间: "+blackMessage,40,465);

        g1.drawString("白方时间: "+whiteMessage,260,465);

        g1.drawRect(428,66,54,20);

        g1.drawString("重新开始",432,80); //重新开始按钮

        g1.drawRect(428,106,54,20);

        g1.drawString("游戏设置",432,120); //游戏设置按钮

        g1.drawRect(428, 146, 54, 20);

        g1.drawString("游戏说明", 432, 160); // 游戏说明按钮

        g1.drawRect(428, 186, 54, 20);

        g1.drawString("退出游戏", 432, 200); // 退出游戏按钮

        g1.drawRect(428, 246, 54, 20);

        g1.drawString("悔棋", 442, 260); // 悔棋

        g1.drawRect(428, 286, 54, 20);

        g1.drawString("认输", 442, 300); // 认输

        for(int i=0;i<15;i++){

            for(int j=0;j<15;j++){

//画实心黑子

                if(allChess[i][j]==1){

                    int tempX=i*25+47;

                    int tempY=j*25+64;

                    g1.setColor(Color.BLACK);

                    g1.fillOval(tempX,tempY,16,16);

                    g1.setColor(Color.BLACK);

                    g1.drawOval(tempX,tempY,16,16);

                }

//画实心白子

                if(allChess[i][j]==2){

                    int tempX=i*25+47;

                    int tempY=j*25+64;

                    g1.setColor(Color.WHITE);

                    g1.fillOval(tempX, tempY, 16, 16);

                    g1.setColor(Color.BLACK);

                    g1.drawOval(tempX, tempY, 16, 16);

                }

            }

        }

        g.drawImage(buf, 0, 0,this);

    }

    @Override

    public void mousePressed(MouseEvent e){

        if(canPlay){

            x=e.getX();

            y=e.getY(); //获得鼠标坐标

            if(x>=55 && x<=405 && y>=72 && y<=420){

//使x,y在0-15的范围

                if((x-55)%25>12){

                    x=(x-55)/25+1;

                }

                else{

                    x=(x-55)/25;

                }

                if((y-72)%25>12){

                    y=(y-72)/25+1;

                }

                else{

                    y=(y-72)/25;

                }

//落子

                if(allChess[x][y]==0){

                    chessX[countX++]=x;

                    chessY[countY++]=y;

                    if(isblack){

                        allChess[x][y]=1;

                        isblack=false;

                        message="白方下子";

                    }

                    else{

                        allChess[x][y]=2;

                        isblack=true;

                        message="黑方下子";

                    }

                    this.repaint();

                    if(this.isWin()){

                        if(allChess[x][y]==1){

                            JOptionPane.showMessageDialog(this, "游戏结束，黑方胜利");

                        }else{

                            JOptionPane.showMessageDialog(this, "游戏结束，白方胜利");

                        }

                        this.canPlay=false; //标识游戏结束

                    }

                }

            }

        }

//重新开始游戏

        if(e.getX()>=428 && e.getY()<=(428+54) && e.getY()>=66 && e.getY()<=(66+20)){

            int result=JOptionPane.showConfirmDialog(this,"是否重新开始游戏？"); //0表示重新开始

            if(result==0){

                restartGame();

            }

        }

//游戏倒计时设置

        if (e.getX()>=428 && e.getX()<=(428+54) && e.getY()>= 106 && e.getY()<=(106+20)) {

            String time=JOptionPane.showInputDialog("请输入游戏的最大时间(单位:分钟),如果输入0,表示没有时间限制:");

            maxTime=Integer.parseInt(time)*60; //将分钟转换为秒，以便后面计算

            if(maxTime<0){

                JOptionPane.showMessageDialog(this,"输入的游戏时间有误,请重新设置!");

            }

            else if(maxTime==0){

                int result=JOptionPane.showConfirmDialog(this,"游戏时间设置成功,是否重新开始游戏?");

//重新开始

                if(result==0){

                    restartGame();

                    timer.suspend(); //挂起线程,以便之后重新启动

                }

            }

            else if(maxTime>0){

                int result = JOptionPane.showConfirmDialog(this,"游戏时间设置成功,是否重新开始游戏?");

                if(result==0){

                    for(int i=0;i<15;i++){

                        for(int j=0;j<15;j++){

                            allChess[i][j]=0;

                        }

                    }

                    for(int i=0;i<15;i++){

                        chessX[i]=-1;

                        chessY[i]=-1;

                    }

                    countX=0;

                    countY=0;

                    message="黑方先行";

                    isblack=true;

                    blackMessage=maxTime/3600+":"+(maxTime/60-maxTime/3600*60)+":"+(maxTime-maxTime/60*60);

                    whiteMessage = maxTime/3600 + ":" + (maxTime/60-maxTime/3600*60) + ":"+ (maxTime-maxTime/60*60);

                    blackTime=maxTime;

                    whiteTime=maxTime;

                    timer.resume();

                    this.canPlay=true;

                    this.repaint();

                }

            }

        }

//游戏说明

        if(e.getX()>=428 && e.getY()<=(428+54) && e.getY()>=146 && e.getY()<=(146+20)){

            JOptionPane.showMessageDialog(this,"规则:横竖斜先连成五子者获胜!");

        }

//退出游戏

        if(e.getX()>=428 && e.getX()<=(428+54) && e.getY()>=186 && e.getY()<=(186+20)) {

            int result=JOptionPane.showConfirmDialog(this,"是否退出游戏?");

            if(result==0){

                System.exit(0);

            }

        }

//悔棋

        if(e.getX()>=428 && e.getX()<=(428+54) && e.getY()>=246 && e.getY()<=(246+20)){

            int result=JOptionPane.showConfirmDialog(this,(isblack==true?"白方悔棋，黑方是否同意？" : "黑方悔棋，白方是否同意？"));

//result=0为悔棋

            if(result==0){

                allChess[chessX[--countX]][chessY[--countY]]=0;

                if(isblack==true){

                    isblack=false;

                }

                else{

                    isblack=true;

                }

                this.repaint(); //重绘棋盘

            }

        }

//认输

        if(e.getX()>=428 && e.getX()<=(428+54) && e.getY()>=286 && e.getY()<=(286+20)){

            int result=JOptionPane.showConfirmDialog(this, "是否认输?");

            if(result==0){

                JOptionPane.showMessageDialog(this,"游戏结束,"+(isblack==true ? "黑方认输，白方获胜!" : "白方认输，黑方获胜!"));

            }

        }

    }

//计时

    @Override

    public void run() {

        if(this.maxTime>0){

            while(true){

                if(isblack){

                    blackTime--;

                    if(blackTime==0){

                        JOptionPane.showMessageDialog(this,"黑方超时,游戏结束");

                        restartGame();

                        timer.suspend();

                    }

                }

                else{

                    whiteTime--;

                    if(whiteTime==0){

                        JOptionPane.showMessageDialog(this,"白方超时,游戏结束");

                        restartGame();

                        timer.suspend();

                    }

                }

                blackMessage=blackTime/3600+":"+(blackTime/60-blackTime/3600*60)+":"+(blackTime-blackTime/60*60);

                whiteMessage=whiteTime/3600+":"+(whiteTime/60-whiteTime/3600*60)+":"+(whiteTime-whiteTime/60*60);

                this.repaint();

                try {

                    Thread.sleep(1000); //设置与时钟同步,1秒钟记一次

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

        }

    }

    @Override

    public void mouseClicked(MouseEvent e) {

// TODO Auto-generated method stub

    }

    @Override

    public void mouseReleased(MouseEvent e) {

// TODO Auto-generated method stub

    }

    @Override

    public void mouseEntered(MouseEvent e) {

// TODO Auto-generated method stub

    }

    @Override

    public void mouseExited(MouseEvent e) {

// TODO Auto-generated method stub

    }

    public void restartGame(){

        for(int i=0;i<15;i++){

            for(int j=0;j<15;j++){

                allChess[i][j]=0; //清空棋盘的棋子

            }

        }

//清空下棋棋子坐标(x,y)的记录

        for(int i=0;i<15;i++){

            chessX[i]=0;

            chessY[i]=0;

        }

        countX=0;

        countY=0;

        message="黑方先行";

        blackMessage="无限制";

        whiteMessage="无限制";

        blackTime=maxTime;

        whiteTime=maxTime;

        isblack=true;

        canPlay=true;

        this.repaint();

    }

    public boolean isWin(){

        boolean flag=false; //定义一标志位

        int count=1; //保存共有相同颜色多少棋子相连,初始值为1

        int color=allChess[x][y]; //color=1(黑子).color=2(白子)

//判断横向是否有5个棋子相连，特点:纵坐标是相同,即allChess[x][y]中y值是相同

        count=this.checkCount(1,0,color);

        if(count>=5){

            flag=true;

        }

        else{

//判断纵向

            count=this.checkCount(0, 1, color);

            if(count>=5){

                flag=true;

            }

            else{

//判断右上,左下

                count=this.checkCount(1,-1, color);

                if(count>=5){

                    flag=true;

                }

                else{

//判断右下,左上

                    count=this.checkCount(1,1,color);

                    if(count>=5){

                        flag=true;

                    }

                }

            }

        }

        return flag;

    }

    public int checkCount(int xChange,int yChange,int color){

        int count=1;

        int tempX=xChange;

        int tempY=yChange; //保存初始值

//全局变量x,y最初为鼠标点击的坐标，经下棋方法已经将x,y的范围变成0-15(遍历整个棋盘,寻找相同颜色的棋子)

        while(x+xChange>=0 && x+xChange<15 && y+yChange>=0 && y+yChange<15 && color==allChess[x+xChange][y+yChange]){

            count++;

            if(xChange!=0) xChange++;

            if(yChange!=0){

                if(yChange!=0){

                    if(yChange>0) yChange++;

                    else {

                        yChange--;

                    }

                }

            }

        }

        xChange=tempX;

        yChange=tempY;

        while(x-xChange>=0 && x-xChange<15 && y-yChange>=0 && y-yChange<15 && color==allChess[x-xChange][y-yChange]){

            count++;

            if(xChange!=0){

                xChange++;

            }

            if(yChange!=0){

                if(yChange>0) yChange++;

                else{

                    yChange--;

                }

            }

        }

        return count;

    }

    public static void main(String[] args) {

        new FiveChessFrame();

    }

}